package com.flyduck.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.flyduck.common.exception.BusinessException;
import com.flyduck.constant.SysConstant;
import com.flyduck.entity.SysMenu;
import com.flyduck.entity.SysRoleMenu;
import com.flyduck.entity.SysUser;
import com.flyduck.manager.NavManager;
import com.flyduck.manager.SysPermissionCacheManager;
import com.flyduck.mapper.SysMenuMapper;
import com.flyduck.mapper.SysRoleMenuMapper;
import com.flyduck.mapper.SysUserMapper;
import com.flyduck.service.SysMenuService;
import com.flyduck.utils.BeanUtils;
import com.flyduck.vo.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author flyduck
 * @since 2024-05-27
 */
@Slf4j
@Service
public class SysMenuServiceImpl implements SysMenuService {

    @Autowired
    private SysUserMapper sysUserMapper;
    @Autowired
    private SysPermissionCacheManager sysPermissionCacheManager;
    @Autowired
    private SysMenuMapper sysMenuMapper;
    @Autowired
    private NavManager navManager;
    @Autowired
    private SysRoleMenuMapper sysRoleMenuMapper;

    @Override
    public UserPermRespVO getNavListByUserId(String username) {
        SysUser sysUser = sysUserMapper.selectOne(
                new LambdaQueryWrapper<SysUser>()
                        .eq(SysUser::getUsername, username)
        );

        //获取权限信息
        List<String> permissionList = sysPermissionCacheManager.getPermissionListByUserId(sysUser.getId());


        //获取导航栏信息
        List<UserPermRespVO.NavDTO> navDTOList = navManager.getNavTreeByUserId(sysUser.getId());

        UserPermRespVO userPermRespVO = new UserPermRespVO();
        userPermRespVO.setMenuList(navDTOList);
        userPermRespVO.setPermissionList(permissionList);
        return userPermRespVO;
    }

    @Override
    public SysMenuDetailsRespVO getMenuDetailsById(Long id) {
        SysMenu sysMenu = sysMenuMapper.selectById(id);
        return BeanUtils.toBean(sysMenu,SysMenuDetailsRespVO.class);
    }

    @Override
    public List<SysMenuTreeRespVO> getMenuTreeList() {
        //获取所有菜单信息
        List<SysMenu> sysMenuList = sysMenuMapper.selectList(
                new LambdaQueryWrapper<SysMenu>()
                .orderByAsc(SysMenu::getOrderNum)
        );
        List<SysMenuTreeRespVO> sysMenuTreeRespVOList = BeanUtils.toBeanList(sysMenuList, SysMenuTreeRespVO.class);

        //转成树状结构
        List<SysMenuTreeRespVO> treeMenu = buildMenuTree(sysMenuTreeRespVOList);
        return treeMenu;
    }

    @Override
    public void saveMenu(SysMenuSaveReqVO sysMenuSaveReqVO) {
        SysMenu sysMenu = BeanUtils.toBean(sysMenuSaveReqVO, SysMenu.class);
        sysMenu.setCreated(LocalDateTime.now());
        sysMenuMapper.insert(sysMenu);
    }

    @Override
    public void updateMenu(SysMenuUpdateReqVO sysMenuUpdateReqVO) {
        SysMenu sysMenu = BeanUtils.toBean(sysMenuUpdateReqVO, SysMenu.class);
        sysMenu.setUpdated(LocalDateTime.now());
        sysMenuMapper.updateById(sysMenu);
        // 清除所有该菜单相关的权限
        sysPermissionCacheManager.clearPermissionListByMenuId(sysMenuUpdateReqVO.getId());
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void deleteById(Long id) {
        Long count = sysMenuMapper.selectCount(
                new LambdaQueryWrapper<SysMenu>()
                        .eq(SysMenu::getParentId, id)
        );
        if (count > 0) {
            throw new BusinessException("请删除子菜单");
        }
        // 清除所有该菜单相关的权限
        sysPermissionCacheManager.clearPermissionListByMenuId(id);
        //删除菜单和角色的中间表
        sysRoleMenuMapper.delete(
                new LambdaQueryWrapper<SysRoleMenu>()
                .eq(SysRoleMenu::getMenuId,id)
        );
        // 删除菜单
        sysMenuMapper.deleteById(id);
    }

    private List<SysMenuTreeRespVO> buildMenuTree(List<SysMenuTreeRespVO> sysMenuTreeRespVOList) {
        // 各自找到自己的孩子（目录的孩子是菜单，菜单的孩子是按钮），如果是目录放到treeMenu里面
        List<SysMenuTreeRespVO>  treeMenu = new ArrayList<>();
        for (SysMenuTreeRespVO directory : sysMenuTreeRespVOList) {
            for (SysMenuTreeRespVO menu : sysMenuTreeRespVOList) {
                if(menu.getParentId().equals(directory.getId())){
                    directory.getChildren().add(menu);
                }
            }
            if(SysConstant.MenuType.DIRECTORY.getCode() == directory.getType()){
                treeMenu.add(directory);
            }
        }
        log.info("菜单树:\n", JSON.toJSONString(treeMenu, true));
        return treeMenu;
    }
}
